from random import choice

from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.shortcuts import render
from rest_framework import status, mixins, viewsets, authentication, exceptions
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.parsers import FormParser, MultiPartParser, JSONParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
from rest_framework.response import Response
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from bangwodai.settings import APIKEY
from users.models import Users, VerifyCode
from users.serializers import SmsSerializer, UserRegSerializer, UserDetailSerializer, SmsLoginSerializer
from yunpian_python_sdk.model import constant as YC
from yunpian_python_sdk.ypclient import YunpianClient


class CustomBackend(ModelBackend):
    """
    短信验证登录规则
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # 不希望用户存在两个，get只能有一个。两个是get失败的一种原因
            # 后期可以添加邮箱验证
            user = Users.objects.get(
                Q(username=username) | Q(phone=username) | Q(email=username))
            # django的后台中密码加密：所以不能password==password
            # UserProfile继承的AbstractUser中有def check_password(self,
            # raw_password):
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class SmsCodeView(mixins.CreateModelMixin,
                  viewsets.GenericViewSet):
    """
    create:
        获取注册验证码
    """
    serializer_class = SmsSerializer
    queryset = VerifyCode.objects.all()
    authentication_classes = ()
    permission_classes = ()

    def generate_code(self):
        """
        生成四位数字的验证码
        """
        seeds = "1234567890"
        random_str = []
        for i in range(4):
            random_str.append(choice(seeds))

        return "".join(random_str)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        # 验证合法
        serializer.is_valid(raise_exception=True)

        phone = serializer.validated_data["phone"]

        # 生成验证码
        code = self.generate_code()

        # 初始化client,apikey作为所有请求的默认值
        clnt = YunpianClient(APIKEY)
        param = {YC.MOBILE: phone, YC.TEXT: '【鲜俊】您的验证码是{}，您正在进行注册，5分钟内有效，如非本人操作，请忽略。'.format(code)}
        sms_status = clnt.sms().single_send(param)

        if sms_status.code() != 0:
            # 发送失败了
            return Response({
                "msg": sms_status.msg()
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            code_record = VerifyCode(code=code, phone=phone)
            code_record.save()
            return Response({
                "msg": "发送成功!"
            }, status=status.HTTP_201_CREATED)

class SmsLoginCodeView(mixins.CreateModelMixin,
                       viewsets.GenericViewSet):
    """
    create:
        获取登录验证码
    """
    serializer_class = SmsLoginSerializer
    queryset = VerifyCode.objects.all()
    authentication_classes = ()
    permission_classes = ()

    def generate_code(self):
        """
        生成四位数字的验证码
        """
        seeds = "1234567890"
        random_str = []
        for i in range(4):
            random_str.append(choice(seeds))

        return "".join(random_str)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        # 验证合法
        serializer.is_valid(raise_exception=True)

        phone = serializer.validated_data["phone"]

        # 生成验证码
        code = self.generate_code()

        # 初始化client,apikey作为所有请求的默认值
        clnt = YunpianClient(APIKEY)
        param = {YC.MOBILE: phone, YC.TEXT: '【鲜俊】您的验证码是{}，您正在进行登录，五分钟内有效，如非本人操作，请忽略。'.format(code)}
        sms_status = clnt.sms().single_send(param)

        if sms_status.code() != 0:
            # 发送失败了
            return Response({
                "msg": sms_status.msg()
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            code_record = VerifyCode(code=code, phone=phone)
            code_record.save()
            return Response({
                "msg": "发送成功!"
            }, status=status.HTTP_201_CREATED)

class UserView(mixins.RetrieveModelMixin,
               mixins.UpdateModelMixin,
               mixins.CreateModelMixin,
               mixins.DestroyModelMixin,
               viewsets.GenericViewSet):
    """
        create:
            用户注册
        retrieve:
            用户个人详细信息
        update:
            修改用户个人信息
        destroy:
            注销用户
        """
    parser_classes = [FormParser, MultiPartParser, JSONParser, ]
    renderer_classes = [JSONRenderer, BrowsableAPIRenderer, ]
    serializer_class = UserRegSerializer
    queryset = Users.objects.all()
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    permission_classes = []

    def get_queryset(self):
        return Users.objects.filter(pk=self.request.user.id)

    def get_serializer_class(self):
        """
        动态选择序列化类，区分注册和详细
        :return:
        """
        if self.action == 'retrieve' or self.action == 'update':
            return UserDetailSerializer
        if self.action == 'create':
            return UserRegSerializer
        return UserDetailSerializer

    def get_permissions(self):
        """
        动态选择权限认证类
        :return:
        """
        if self.action == 'retrieve' or self.action == 'update' or self.action == 'destroy':
            return [IsAuthenticated()]
        else:
            return []


    # 虽然继承了Retrieve可以获取用户详情，但是并不知道用户的id，所有要重写get_object方法
    # 重写get_object方法，就知道是哪个用户了
    def get_object(self):
        return self.request.user

# class PasswordLoginView(APIView):
#     queryset = Users.objects.all()
#     serializer_class = PasswordLoginSerializer
#
#     def post(self):
#         pass
